package com.bbird.od.finance.service.domain;

import com.alibaba.excel.EasyExcel;
import com.bbird.od.finance.service.models.JDBankFlow;
import com.bbird.od.finance.service.models.ReconciliationResult;
import com.bbird.od.finance.service.models.type.BankCostType;
import com.bbird.od.finance.service.models.type.BankType;
import com.bbird.od.finance.service.models.type.YesOrNo;
import com.bbird.od.finance.service.listener.FlowExcelListener;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * @author ziyang Kuang
 * @date 2020/11/16
 * @describe
 */

@Slf4j
public class JDReconciliationHandler extends AbstractReconciliationHandler<JDBankFlow> {

    @Override
    protected void bankToErpCheck(List<JDBankFlow> bankFlows) {
        Map<String, ReconciliationResult> reconciliationResultMap = reconciliationResultsMapThreadLocal.get();

        bankFlows.forEach(bankFlow -> {
            BankCostType bankCostType = BankCostType.getByLabel(bankFlow.getCostType());
            if (bankCostType == null) {
                log.error("[{}] 银行流水费用项类型转换失败， costType:{}", this.getBankType().getLabel(), bankFlow.getCostType());
                return;
            }

            ReconciliationResult result = reconciliationResultMap.get(bankFlow.getHomeOrderNumber());
            if (result == null) {
                // 预收款
                result = new ReconciliationResult();
                result.setHomeOrderNumber(bankFlow.getHomeOrderNumber());
                reconciliationResultMap.put(bankFlow.getHomeOrderNumber(), result);
            }

            // 银行流水金额
            BigDecimal amount = bankFlow.getActualAmount();
            if ("取消退款单".equals(bankFlow.getBankOrderType()) || "售后服务单".equals(bankFlow.getBankOrderType())) {
                // 退款订单
                refund(bankCostType, result, amount);
            } else {
                statisticsReceivable(bankCostType, result, amount);
            }
        });
    }

    @Override
    protected BigDecimal calcReceivedAmount(ReconciliationResult reconciliationResult) {
        // 实收金额 = 实收货款+实收运费+退货款+退运费
        BigDecimal receivedAmount = reconciliationResult.getActualReceivableGoodsAmount()
                .add(reconciliationResult.getActualReceivableTransportationAmount())
                .add(reconciliationResult.getRefundReceivableGoodsAmount())
                .add(reconciliationResult.getRefundReceivableTransportationAmount());
        return receivedAmount;
    }

    @Override
    List<JDBankFlow> analyseBankFlow(File bankFlowExcel) {
        FlowExcelListener<JDBankFlow> listener = new FlowExcelListener(this.getBankType(), bankFlowExcel.getName());
        EasyExcel.read(bankFlowExcel, JDBankFlow.class, listener).headRowNumber(1).sheet().doRead();
        return listener.getDataList();
    }

    @Override
    BankType getBankType() {
        return BankType.JD;
    }

    /**
     * 退款操作
     *
     * @param bankCostType
     * @param result
     * @param amount
     */
    private void refund(BankCostType bankCostType, ReconciliationResult result, BigDecimal amount) {
        result.setRefunded(YesOrNo.YES);
        result.setRefundAmount(result.getRefundAmount().add(amount));
        switch (bankCostType) {
            case JD_GOODS_FEE:
                result.setRefundReceivableGoodsAmount(result.getRefundReceivableGoodsAmount().add(amount));
                break;
            case JD_DELIVERY_FEE:
                result.setRefundReceivableTransportationAmount(result.getRefundReceivableTransportationAmount().add(amount));
                break;
            case JD_COMMISSION_FEE:
                result.setRefundCommission(result.getRefundCommission().add(amount));
                break;
            case JD_BEAN_FEE:
                result.setRefundJingdou(result.getRefundJingdou().add(amount));
                break;
            default:
                break;
        }
    }

    /**
     * 计算应收
     */
    private void statisticsReceivable(BankCostType bankCostType, ReconciliationResult result, BigDecimal amount) {
        switch (bankCostType) {
            case JD_GOODS_FEE:
                result.setActualReceivableGoodsAmount(result.getActualReceivableGoodsAmount().add(amount));
                break;
            case JD_DELIVERY_FEE:
                result.setActualReceivableTransportationAmount(result.getActualReceivableTransportationAmount().add(amount));
                break;
            case JD_COMMISSION_FEE:
                result.setCommission(result.getCommission().add(amount));
                break;
            case JD_BEAN_FEE:
                result.setJingdou(result.getJingdou().add(amount));
                break;
            default:
                break;
        }
    }
}
